home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 748 / 748.xpi / content / xmlhttprequester.js < prev   
Text File  |  2010-02-11  |  5KB  |  139 lines

  1. function GM_xmlhttpRequester(unsafeContentWin, chromeWindow) {
  2.   this.unsafeContentWin = unsafeContentWin;
  3.   this.chromeWindow = chromeWindow;
  4. }
  5.  
  6. // this function gets called by user scripts in content security scope to
  7. // start a cross-domain xmlhttp request.
  8. //
  9. // details should look like:
  10. // {method,url,onload,onerror,onreadystatechange,headers,data}
  11. // headers should be in the form {name:value,name:value,etc}
  12. // can't support mimetype because i think it's only used for forcing
  13. // text/xml and we can't support that
  14. GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  15.   if (!GM_apiLeakCheck("GM_xmlhttpRequest")) {
  16.     return;
  17.   }
  18.  
  19.   GM_log("> GM_xmlhttpRequest.contentStartRequest");
  20.  
  21.   // Store this value by looking at it exactly once, and guaranteeing (via null
  22.   // prepend) that it is a string, and not an object that might play tricks
  23.   // with multiple .toString() calls.
  24.   var url = '' + details.url;
  25.  
  26.   try {
  27.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  28.                     .getService(Components.interfaces.nsIIOService);
  29.     var scheme = ioService.extractScheme(url);
  30.   } catch (e) {
  31.     // A malformed URL won't be parsed properly.
  32.     throw new Error('Invalid URL: '+url);
  33.   }
  34.  
  35.   // This is important - without it, GM_xmlhttpRequest can be used to get
  36.   // access to things like files and chrome. Careful.
  37.   switch (scheme) {
  38.     case "http":
  39.     case "https":
  40.     case "ftp":
  41.         var req = new this.chromeWindow.XMLHttpRequest();
  42.         GM_hitch(this, "chromeStartRequest", url, details, req)();
  43.       break;
  44.     default:
  45.       throw new Error("Invalid url: " + url);
  46.   }
  47.  
  48.   GM_log("< GM_xmlhttpRequest.contentStartRequest");
  49.  
  50.   return {
  51.     abort: function() {
  52.       req.abort();
  53.     }
  54.   };
  55. };
  56.  
  57. // this function is intended to be called in chrome's security context, so
  58. // that it can access other domains without security warning
  59. GM_xmlhttpRequester.prototype.chromeStartRequest =
  60. function(safeUrl, details, req) {
  61.   GM_log("> GM_xmlhttpRequest.chromeStartRequest");
  62.  
  63.   this.setupRequestEvent(this.unsafeContentWin, req, "onload", details);
  64.   this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details);
  65.   this.setupRequestEvent(this.unsafeContentWin, req, "onreadystatechange",
  66.                          details);
  67.  
  68.   req.open(details.method, safeUrl);
  69.  
  70.   if (details.overrideMimeType) {
  71.     req.overrideMimeType(details.overrideMimeType);
  72.   }
  73.  
  74.   if (details.headers) {
  75.     for (var prop in details.headers) {
  76.       req.setRequestHeader(prop, details.headers[prop]);
  77.     }
  78.   }
  79.  
  80.   var body = details.data ? details.data : null;
  81.   if (details.binary) {
  82.     // xhr supports binary?
  83.     if (!req.sendAsBinary) {
  84.       var err = new Error("Unavailable feature: " +
  85.               "This version of Firefox does not support sending binary data " +
  86.               "(you should consider upgrading to version 3 or newer.)");
  87.       GM_logError(err);
  88.       throw err;
  89.     }
  90.     req.sendAsBinary(body);
  91.   } else {
  92.     req.send(body);
  93.   }
  94.  
  95.   GM_log("< GM_xmlhttpRequest.chromeStartRequest");
  96. }
  97.  
  98. // arranges for the specified 'event' on xmlhttprequest 'req' to call the
  99. // method by the same name which is a property of 'details' in the content
  100. // window's security context.
  101. GM_xmlhttpRequester.prototype.setupRequestEvent =
  102. function(unsafeContentWin, req, event, details) {
  103.   GM_log("> GM_xmlhttpRequester.setupRequestEvent");
  104.  
  105.   if (details[event]) {
  106.     req[event] = function() {
  107.       GM_log("> GM_xmlhttpRequester -- callback for " + event);
  108.  
  109.       var responseState = {
  110.         // can't support responseXML because security won't
  111.         // let the browser call properties on it
  112.         responseText: req.responseText,
  113.         readyState: req.readyState,
  114.         responseHeaders: null,
  115.         status: null,
  116.         statusText: null,
  117.         finalUrl: null
  118.       };
  119.       if (4 == req.readyState && 'onerror' != event) {
  120.         responseState.responseHeaders = req.getAllResponseHeaders();
  121.         responseState.status = req.status;
  122.         responseState.statusText = req.statusText;
  123.         responseState.finalUrl = req.channel.URI.spec;
  124.       }
  125.  
  126.       // Pop back onto browser thread and call event handler.
  127.       // Have to use nested function here instead of GM_hitch because
  128.       // otherwise details[event].apply can point to window.setTimeout, which
  129.       // can be abused to get increased priveledges.
  130.       new XPCNativeWrapper(unsafeContentWin, "setTimeout()")
  131.         .setTimeout(function(){details[event](responseState);}, 0);
  132.  
  133.       GM_log("< GM_xmlhttpRequester -- callback for " + event);
  134.     }
  135.   }
  136.  
  137.   GM_log("< GM_xmlhttpRequester.setupRequestEvent");
  138. };
  139.